<?php

namespace app\models;

use yii\data\ActiveDataProvider;
use yii\db\ActiveRecord;
use yii\filters\RateLimitInterface;
use yii\web\IdentityInterface;

/**
 * @property mixed id
 * @property string password
 * @property string token
 * @property int created_at
 * @property int updated_at
 * @property int token_expired_time
 */
class User extends ActiveRecord implements IdentityInterface, RateLimitInterface
{
//    public $role_name = '';
//    public $department_name = '';
    /** ------------------------- 验证规则，字段输入输出规则  -------------------------------*/
    // 使用load 与 save 方法时此规则会起作用
    // 此规则必须配置，否则字段不能load到模型的属性。
    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['username', 'password', 'department_id', 'role_id'], 'required'],
            [['department_id', 'role_id','id','status','part_id'], 'integer'],
            [['username', 'password', 'name', 'avatar'], 'string', 'max' => 255],
            [['username'], 'unique'],
            ];
    }

    /**
     * 模型字段过滤器。当它配合数据处理器对象时，会起效
     * @return array
     */
    public function fields()
    {
        $fields = parent::fields();
        unset($fields['password'],$fields['token'],$fields['token_expired_time'],$fields['rateLimit'],
            $fields['allowance'],$fields['allowance_updated_at']);
        //以下两句自定义输出字段依赖于关联关系方法：getRole()与getDepartment()
        return $fields;
    }

    public function extraFields()
{
    $fields['role_name'] = function ($model){
        return $model->role->name;
    };
    $fields['department_name'] = function ($model){
        return $model->department->name;
    };
    $fields['department_branch'] = function ($model){
        return $model->department->branch_id;
    };
    $fields['branch_name'] = function ($model){
        return $model->branch->name;
    };
    $fields['branch'] = function ($model){
        return $model->branch;
    };
    $fields['part_name'] = function ($model){
        return $model->part;
    };
    return $fields;
}

    public function scenarios()
    {
        $scenarios = parent::scenarios(); // TODO: Change the autogenerated stub
        $scenarios['update'] = $scenarios['default'];
        unset( $scenarios['update']['id'],$scenarios['update']['username'],$scenarios['update']['password']);
        return $scenarios;
    }
    /**----------------------------用户自定义资源获取与操作方法---------------------------------------------*/
    /**
     * @return bool
     */
    public function create(){
        // 这两种加密方法太慢
//        $this->token = Yii::$app->security->generateRandomString().'_'.time();
//        $this->password = Yii::$app->getSecurity()->generatePasswordHash($this->password);
        $this->token = sha1(time().mt_rand(0,1000));
        $this->password = sha1($this->password);
        $this->created_at = $this->updated_at = time();
        $this->token_expired_time = $this->created_at + 1800;
        $this->username = $this->name;
        if($this->save())
            return true;
        return false;
    }

    /**
     * 当token过期时，重新改变token
     */
    public function updateToken(){
        $this->token = sha1(time().mt_rand(0,1000));
        $this->token_expired_time = $this->created_at + 1800;
        $this->save();
    }

    /**
     * 每次访问token续期半小时
     */
    public function updateTokenExpiredTime(){
        $this->token_expired_time += 1800;
        $this->save();
    }

    /**
     * @return bool
     */
    public function _update(){
        $this->updated_at = time();
        if($this->save())
            return true;
        return false;
    }

    /**
     * @param $username
     * @param $password
     * @return string
     */
    public static function getToken($username,$password){
        $password = sha1($password);
        $res = User::findOne(['username'=>$username,'password'=>$password]);
        if($res)
            return $res->token;
        return null;
    }
/**----------------------------关系类方法---------------------------------------------*/
    public function getRole(){
        return $this->hasOne(Role::class,['id'=>'role_id']);
    }

    public function getDepartment(){
        return $this->hasOne(Department::class,['id'=>'department_id']);
    }

    public function getPart(){
        return $this->hasOne(part::class,['id'=>'part_id']);
    }

    public function getBranch(){
         return $this->hasOne(Branch::class,['id'=>'branch_id'])
         ->via('department');
        // 以下的写法也是一样的
//        return $this->hasOne(Branch::class,['id'=>'branch_id'])
//            ->viaTable('{{%department}}',['id'=>'department_id']);

    }

/**-----------------------实现接口----------------------------------------------*/

    /**
     * @param mixed $token
     * @param null $type
     * @return User|null|IdentityInterface
     */
    public static function findIdentityByAccessToken($token, $type = null)
    {
        // TODO: Implement findIdentityByAccessToken() method.
        return User::findOne(['token' => $token]);
    }

    /**
     * @param int|string $id
     * @return User|null|IdentityInterface
     */
    public static function findIdentity($id)
    {
        // TODO: Implement findIdentity() method.
        return User::findOne($id);
    }

    /**
     * @return int|mixed|string
     */
    public function getId()
    {
        // TODO: Implement getId() method.
        return $this->id;
    }

    /**
     * @return string|void
     */
    public function getAuthKey()
    {
        // TODO: Implement getAuthKey() method.
    }

    /**
     * @param string $authKey
     * @return bool|void
     */
    public function validateAuthKey($authKey)
    {
        // TODO: Implement validateAuthKey() method.
    }

    //---------------------------速率限制接口中
    //限制每个用户每秒的访问频率
    public function getRateLimit($request, $action)
    {
        // TODO: Implement getRateLimit() method.
        return [$this->rateLimit, 1]; // $rateLimit requests per second
    }

    public function loadAllowance($request, $action)
    {
        // TODO: Implement loadAllowance() method.
        return [$this->allowance, $this->allowance_updated_at];
    }

    public function saveAllowance($request, $action, $allowance, $timestamp)
    {
        // TODO: Implement saveAllowance() method.
        $this->allowance = $allowance;
        $this->allowance_updated_at = $timestamp;
        $this->save();
    }


}
